package sm.def;

import java.util.Date;

import sm.codec.type.Logical;
import sm.codec.type.NullValue;
import sm.codec.type.Operator;
import sm.codec.type.Struct;
import sm.codec.type.Variable;

public enum Type {
	UNKNOWN(0, "unknown"), NUMBER(1, "number"), CHARACTER(2, "character"), TIME(
			3, "date/time"), LOGICAL(4, "logical"), LABEL(5, "label"), RECORD(
			6, "record"), OFFSET(7, "offset"), ARRAY(8, "array"), STRUCTURE(9,
			"structure"), OPERATOR(10, "operator"), EXPRESSION(11, "expression"), PSEUDO(
			12, "pseudo"), LOCALVARIABLE(13, "local variable"), GLOBALVARIABLE(
			14, "global variable"), MEMBER(15, "member");

	private int number;

	private String name;

	public int getNumber() {
		return number;
	}

	public String getName() {
		return name;
	}

	private Type(int number, String name) {
		this.number = number;
		this.name = name;
	}

	public static boolean isPrimitiveType(int type) {
		if (type == Type.STRUCTURE_TYPE || type == Type.ARRAY_TYPE) {
			return false;
		} else {
			return true;
		}
	}

	public static Type getType(int number) {
		switch (number) {
		case NUMBER_TYPE:
			return NUMBER;
		case CHARACTER_TYPE:
			return CHARACTER;
		case TIME_TYPE:
			return TIME;
		case LOGICAL_TYPE:
			return LOGICAL;
		case LABEL_TYPE:
			return LABEL;
		case RECORD_TYPE:
			return RECORD;
		case OFFSET_TYPE:
			return OFFSET;
		case ARRAY_TYPE:
			return ARRAY;
		case STRUCTURE_TYPE:
			return STRUCTURE;
		case OPERATOR_TYPE:
			return OPERATOR;
		case EXPRESSION_TYPE:
			return EXPRESSION;
		case PSEUDO_TYPE:
			return PSEUDO;
		case LOCALVARIABLE_TYPE:
			return LOCALVARIABLE;
		case GLOBALVARIABLE_TYPE:
			return GLOBALVARIABLE;
		case MEMBER_TYPE:
			return MEMBER;
		default:
			return UNKNOWN;
		}
	}

	public NullValue getNullValue() {
		switch (number) {
		case NUMBER_TYPE:
			return NullValue.NumberNull;
		case CHARACTER_TYPE:
			return NullValue.CharacterNull;
		case TIME_TYPE:
			return NullValue.TimeNull;
		case LOGICAL_TYPE:
			return NullValue.LogicalNull;
		case LABEL_TYPE:
			return NullValue.LabelNull;
		case RECORD_TYPE:
			return NullValue.RecordNull;
		case OFFSET_TYPE:
			return NullValue.OffsetNull;
		case ARRAY_TYPE:
			return NullValue.ArrayNull;
		case STRUCTURE_TYPE:
			return NullValue.StructureNull;
		case OPERATOR_TYPE:
			return NullValue.OperatorNull;
		case EXPRESSION_TYPE:
			return NullValue.ExpressionNull;
		case PSEUDO_TYPE:
			return NullValue.PseudoNull;
		case LOCALVARIABLE_TYPE:
			return NullValue.LocalVariableNull;
		case GLOBALVARIABLE_TYPE:
			return NullValue.GlobalVariableNull;
		case MEMBER_TYPE:
			return NullValue.MemberNull;

		default:
			return null;
		}
	}

	public static int getTypeNumber(Object obj) {
		int type = 0;
		if (obj instanceof NullValue) {
			type = ((NullValue) obj).getType();
		} else if (obj instanceof Double) {
			type = Type.NUMBER_TYPE;
		} else if (obj instanceof String) {
			type = Type.CHARACTER_TYPE;
		} else if (obj instanceof Date) {
			type = Type.TIME_TYPE;
		} else if (obj instanceof Logical || obj instanceof Boolean) {
			type = Type.LOGICAL_TYPE;
		} else if (obj instanceof Struct) {
			type = ((Struct) obj).getType();
		} else if (obj instanceof Operator) {
			type = Type.OPERATOR_TYPE;
		} else if (obj instanceof Variable) {
			type = ((Variable) obj).getType();
		}
		return type;
	}

	public static String getTypeName(Object obj) {
		int type = getTypeNumber(obj);
		if (type != 0) {
			return getType(type).name;
		} else {
			return obj.getClass().getName();
		}
	}

	public static final int NUMBER_TYPE = 1;

	public static final int CHARACTER_TYPE = 2;

	public static final int TIME_TYPE = 3;

	public static final int LOGICAL_TYPE = 4;

	public static final int LABEL_TYPE = 5;

	public static final int RECORD_TYPE = 6;

	public static final int OFFSET_TYPE = 7;

	public static final int ARRAY_TYPE = 8;

	public static final int STRUCTURE_TYPE = 9;

	public static final int OPERATOR_TYPE = 10;

	public static final int EXPRESSION_TYPE = 11;

	public static final int PSEUDO_TYPE = 12;

	public static final int LOCALVARIABLE_TYPE = 13;

	public static final int GLOBALVARIABLE_TYPE = 14;

	public static final int MEMBER_TYPE = 15;

}
